package jumpingnotes.dao.hibernate;

import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Example;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.util.Assert;

import jumpingnotes.dao.GenericDAO;
import jumpingnotes.dao.Sorter;
import jumpingnotes.dao.SorterHelper;

public class GenericHibernateDAO<T> extends HibernateDaoSupport implements GenericDAO<T>
{
	private Class<T> persistentClass;

	public GenericHibernateDAO(Class<T> persistentClass)
	{
		this.persistentClass = persistentClass;
	}

	public Class<T> getPersistentClass()
	{
		return persistentClass;
	}

	@SuppressWarnings("unchecked")
	public T findById(int id)
	{
		return (T) getHibernateTemplate().load(getPersistentClass(), id);
	}

	@SuppressWarnings("unchecked")
	public List<T> findAll(final int firstResult, final int maxResults, final Sorter sorter)
	{
		return (List) getHibernateTemplate().execute(new HibernateCallback()
		{
			public Object doInHibernate(Session session) throws HibernateException
			{
				Criteria criteria = session.createCriteria(getPersistentClass());
				SorterHelper.addSorter(criteria, sorter);
				if (firstResult >= 0)
					criteria.setFirstResult(firstResult);
				if (maxResults > 0)
					criteria.setMaxResults(maxResults);
				return criteria.list();
			}
		}, true);
	}

	@SuppressWarnings("unchecked")
	public List<T> findByExample(final T exampleEntity, final int firstResult, final int maxResults, final Sorter sorter)
	{
		Assert.notNull(exampleEntity, "Example entity must not be null");
		return (List) getHibernateTemplate().execute(new HibernateCallback()
		{
			public Object doInHibernate(Session session) throws HibernateException
			{
				Criteria criteria = session.createCriteria(getPersistentClass());
				criteria.add(Example.create(exampleEntity).enableLike());
				SorterHelper.addSorter(criteria, sorter);
				if (firstResult >= 0)
					criteria.setFirstResult(firstResult);
				if (maxResults > 0)
					criteria.setMaxResults(maxResults);
				return criteria.list();
			}
		}, true);
	}

	@SuppressWarnings("unchecked")
	public int save(T entity)
	{
		return (Integer) getHibernateTemplate().save(entity);
	}

	public void update(T entity)
	{
		getHibernateTemplate().update(entity);
	}

	public void delete(T entity)
	{
		getHibernateTemplate().delete(entity);
	}
}
